﻿using D.UtilOrm;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;

namespace D.UtilSqlsugarOrm
{
    public static class SqlSugarOrm
    {
        /// <summary>
        /// Sqlsugar 上下文初始化
        /// </summary>
        /// <param name="services"></param>
        public static void AddSqlSugar(this IServiceCollection services, DbConfig dbConfig)
        {
            SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
            {
                ConnectionString = dbConfig.ConnectionString,
                DbType = GetDbType(dbConfig.DbType),
            });
            // 初始化数据库表结构及种子数据
            InitDatabase(sqlSugar, dbConfig);

            services.AddSingleton<ISqlSugarClient>(sqlSugar); // 单例注册
            //services.AddScoped(typeof(SqlSugarRepository<>)); // 仓储注册
            //services.AddUnitOfWork<SqlSugarUnitOfWork>(); // 事务与工作单元注册
        }

        /// <summary>
        /// 配置Aop
        /// </summary>
        /// <param name="db"></param>
        public static void SetDbAop(SqlSugarScopeProvider db)
        {
            var config = db.CurrentConnectionConfig;

            // 设置超时时间
            db.Ado.CommandTimeOut = 30;

            // 打印SQL语句
            db.Aop.OnLogExecuting = (sql, pars) =>
            {
                var originColor = Console.ForegroundColor;
                if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
                    Console.ForegroundColor = ConsoleColor.Green;
                if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
                    Console.ForegroundColor = ConsoleColor.Yellow;
                if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
                    Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("【" + DateTime.Now + "——执行SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n");
                Console.ForegroundColor = originColor;
                //App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
            };
            db.Aop.OnError = (ex) =>
            {
                if (ex.Parametres == null) return;
                var originColor = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.DarkRed;
                var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
                Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n");
                Console.ForegroundColor = originColor;
                //App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}");
            };

            // 数据审计
            db.Aop.DataExecuting = (oldValue, entityInfo) =>
            {
                //if (entityInfo.OperationType == DataFilterType.InsertByObject)
                //{
                //// 主键(long类型)且没有值的---赋值雪花Id
                //if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
                //{
                //    var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
                //    if (id == null || (long)id == 0)
                //        entityInfo.SetValue(YitIdHelper.NextId());
                //}
                //if (entityInfo.PropertyName == "CreateTime")
                //    entityInfo.SetValue(DateTime.Now);

                //}
                //if (entityInfo.OperationType == DataFilterType.UpdateByObject)
                //{
                //    if (entityInfo.PropertyName == "UpdateTime")
                //        entityInfo.SetValue(DateTime.Now);
                //}
            };
        }

        /// <summary>
        /// 初始化数据库
        /// </summary>
        /// <param name="db"></param>
        /// <param name="config"></param>
        private static void InitDatabase(SqlSugarScope db, DbConfig config)
        {

            //SqlSugarScopeProvider dbProvider = db.GetConnectionScope(config.ConfigId);

            //// 创建数据库
            //var dbType = GetDbType(config.DbType);
            //if (dbType != DbType.Oracle)
            //    dbProvider.DbMaintenance.CreateDatabase();

            //// 获取所有实体表-初始化表结构
            //var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false));
            //if (!entityTypes.Any()) return;
            //foreach (var entityType in entityTypes)
            //{
            //    var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
            //    if (tAtt != null && tAtt.configId.ToString() != config.ConfigId) continue;
            //    if (tAtt == null && config.ConfigId != SqlSugarConst.ConfigId) continue;

            //    var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>();
            //    if (splitTable == null)
            //        dbProvider.CodeFirst.InitTables(entityType);
            //    else
            //        dbProvider.CodeFirst.SplitTables().InitTables(entityType);
            //}

            //if (!config.EnableInitSeed) return;

            // 获取所有种子配置-初始化数据
            //var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
            //    && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))));
            //if (!seedDataTypes.Any()) return;
            //foreach (var seedType in seedDataTypes)
            //{
            //    var instance = Activator.CreateInstance(seedType);

            //    var hasDataMethod = seedType.GetMethod("HasData");
            //    var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
            //    if (seedData == null) continue;

            //    var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
            //    var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
            //    if (tAtt != null && tAtt.configId.ToString() != config.ConfigId) continue;
            //    if (tAtt == null && config.ConfigId != SqlSugarConst.ConfigId) continue;

            //    var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
            //    if (entityInfo.Columns.Any(u => u.IsPrimarykey))
            //    {
            //        // 按主键进行批量增加和更新
            //        var storage = dbProvider.StorageableByObject(seedData.ToList()).ToStorage();
            //        storage.AsInsertable.ExecuteCommand();
            //        var ignoreUpdate = hasDataMethod.GetCustomAttribute<IgnoreUpdateAttribute>();
            //        if (ignoreUpdate == null) storage.AsUpdateable.ExecuteCommand();
            //    }
            //    else
            //    {
            //        // 无主键则只进行插入
            //        if (!dbProvider.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any())
            //            dbProvider.InsertableByObject(seedData.ToList()).ExecuteCommand();
            //    }
            //}
        }

        public static DbType GetDbType(int dataType)
        {
            if (dataType == 0)
            {
                return DbType.MySql;
            }
            else if (dataType == 1)
            {
                return DbType.SqlServer;
            }
            else if (dataType == 2)
            {
                return DbType.Sqlite;
            }
            else if (dataType == 3)
            {
                return DbType.Oracle;
            }
            else if (dataType == 4)
            {
                return DbType.PostgreSQL;
            }
            else if (dataType == 5)
            {
                return DbType.Dm;
            }
            else if (dataType == 6)
            {
                return DbType.Kdbndp;
            }
            else if (dataType == 7)
            {
                return DbType.Oscar;
            }
            //else if (dataType == 8)
            //{
            //    return DbType.MySqlConnector;
            //}
            else if (dataType == 9)
            {
                return DbType.Access;
            }
            else if (dataType == 10)
            {
                return DbType.OpenGauss;
            }
            else if (dataType == 11)
            {
                return DbType.QuestDB;
            }
            else if (dataType == 12)
            {
                return DbType.HG;
            }
            else if (dataType == 13)
            {
                return DbType.ClickHouse;
            }
            else if (dataType == 14)
            {
                return DbType.GBase;
            }
            else if (dataType == 15)
            {
                return DbType.Odbc;
            }
            return 0;
        }
    }
}